`define VERSION 32'h00000011

//`define READ_INS 1

module debugger_ft232h (
    input           clk,
    input           clk_50M,
    input           clk_25M,
    input           reset_n,

    //external
inout  [7:0] ft_AD,
input  ft_AC7,//1:hi speed 0:command
output ft_AC6_NOE,//ready
input  ft_AC5_CLKOUT,
input  ft_AC5_SCLKOUT,
input  ft_AC5_RCLKOUT,
output ft_AC4_NSIWU,
output ft_AC3_NWR,//1
output ft_AC2_NRD,//1
input  ft_AC1_NTXE,// 1:cmd 0:dat (先送数据后cmd) TXE# OUTPUT When high, do not write data into the FIFO. When low, data can be written into the FIFO by driving WR# low. When in synchronous mode, data is transferred on every clock that TXE# and WR# are both low.
input  ft_AC0_NRXF,// out to pc RXF# OUTPUT When high, do not read data from the FIFO. When low, there is data available in the FIFO which can be read by driving RD# low. When in synchronous mode, data is transferred on every clock that RXF# and RD# are both low. Note that the OE# pin must be driven low at least 1 clock period before asserting RD# low.
//
    output          ch341a_ack,//debug模块请求置1，cs0拉低置0
    output          ch341a_miso,//data out
    input           ch341a_mosi,
    input           ch341a_sck,
    input           ch341a_cs2,//data out
    input           ch341a_cs1,//data in
    input           ch341a_cs0,//cmd in /data out

    //cpu
    output reg          debug_reset_n,
    output reg          halt_debug,
    output reg          debug_step,
    input               halt_cpu,
    //input        [31:0] curr_data,
    //input        [31:0] pcResult,
    //input        [31:0] private_offset,
    //input        [31:0] private_offset_rear,
    input        [31:0] pc,
    input        [31:0] cpu_address,
    input               irq_enable,
    //input        [31:0] irq_addr,

    output reg          debug_rw,
    output reg   [2:0]  debug_rw_cmd,
    output              debug_read_ins,
    output              debug_ins_hold_value,
    output reg  [31:0]  debug_address_data,
    output reg  [31:0]  debug_address_ins,
    output reg  [31:0]  debug_writedata_data,

    input       [31:0]  avm_m0_address,
    input               avm_m0_request,
    input               avm_m0_rw,
    input       [31:0]  avm_m0_readdata,
    input               avm_m0_waitrequest,
    input               avm_m1_read,
    input       [31:0]  avm_m1_readdata,
    input               avm_m1_waitrequest,
    input               irq_req,
    input         [4:0] irq_id,

    output       [5:0]  debug_regAddr,
    input       [31:0]  debug_regData,

    output        [7:0] pc_record_index_read,
    input        [35:0] pc_record_data,
    input        [31:0] pc_record_index,
    
    output        [7:0] debug_stash_index_read,
    input        [31:0] debug_stash_data,
    input         [7:0] debug_stash_index,

    //spirom
    output reg        spirom_debug_read_req     ,
    input             spirom_debug_read_ack     ,
    input       [7:0] spirom_debug_read_data    ,
    output reg        spirom_debug_write_req    ,
    input             spirom_debug_write_ack    ,
    output reg  [7:0] spirom_debug_write_data   ,
    output reg        spirom_debug_cs           ,

    //vga
    output reg        vga_control_by_debugger,
    input             vga_control_by_debugger_accepted,
    output reg        vga_debugger_read_line_req,
    output      [9:0] vga_debugger_read_line_burst,
    input             vga_debugger_read_line_ack,
    output     [15:0] vga_debugger_read_line_addr,//128Mbyte range 2k byte/line
    output      [1:0] vga_debugger_read_line_part,
    
    output      [9:0] vga_debugger_read_pixel_addr,
    output            vga_debugger_read_pixel_clk,
    input      [15:0] vga_debugger_read_pixel_data,

    output reg [31:0] debug_hid,
    output reg        debug_hid_req,

    //misc
    output reg        debug_flg,
    input      [31:0] debug_tx_to_pc,
    input             debug_tx_to_pc_valid,
    output reg        debug_tx_to_pc_read,
    output reg [31:0] debug_rx_from_pc,
    output reg        debug_rx_from_pc_valid,
    input             debug_rx_from_pc_read,
    output reg [31:0] debug_vga_base_addr,
    input      [31:0] memSize,
    input      [15:0] vga_base_addr,
    output reg        cpu_clk_sel,


    output reg debug_commandFifo,
    output reg [31:0] debug_commandFifoAddr,
    input [31:0] debug_command_read_cur,
    input [31:0] debug_command_write_cur,
    input [31:0] debug_max_command_length,
    input [35:0] debug_q_command,



  input dummy
);
// `ifdef isISE
//   assign vga_debugger_read_line_burst = 256;
// `endif
// `ifdef isALTERA
//   assign vga_debugger_read_line_burst = 512;
// `endif

    assign          ch341a_ack = 0;
    assign          ch341a_miso = 0;

assign vga_debugger_read_line_burst = 512;//字

assign pc_record_index_read = debug_address[7:0];
assign debug_stash_index_read = debug_address[7:0];


localparam FIFO_SIZE = 1;

reg [FIFO_SIZE:0] fpga_addr;
wire [31:0] fpga_read_data;
reg         fpga_write;
reg  [31:0] fpga_write_data;

assign ft_AC4_NSIWU = 1;

localparam MEM_READ             = 0;
localparam MEM_WRITE            = 1;
localparam INS_READ             = 2;
localparam REG_READ             = 3;
localparam MEM_READ_TRANS       = 4;
localparam MEM_WRITE_TRANS      = 5;
localparam INS_READ_TRANS       = 6;
localparam VGA_TRANS            = 7;


wire ft_out_to_pc = (mem_cmd==MEM_READ_TRANS) || (mem_cmd==INS_READ_TRANS) || (mem_cmd==VGA_TRANS);

  wire hiSpeed = ft_AC7==1;//1:hi speed 弱上拉 0:command 强下拉

  assign ft_AD = hiSpeed ? (ft_out_to_pc ? ft_AD_out : 8'hzz) : (ft_AC0_NRXF ? debug_data_out_buff[7:0] : 8'hzz);//ft_AC0_NRXF:out
  assign ft_AC6_NOE = hiSpeed ? ft_out_to_pc : command_ack;////1:hi speed 0:command


  reg command_req_ori;
  reg command_ack;
  reg debug_data_send;
  reg [31:0] debug_data_out;
  reg [31:0] data;//先低后高
  reg [7:0] command;
  assign debug_regAddr = debug_address[5:0];
  reg transfer_regWriteEna_reg;

  reg [31:0] debug_data_out_buff;

  always @(posedge ft_AC5_CLKOUT or negedge reset_n) begin
    if (!reset_n) begin
      command <= 0;
      data <= 0;
      command_req_ori <= 0;
      debug_data_out_buff <= 0;
    end else begin
      if(!hiSpeed)begin
        if(ft_AC1_NTXE==0)begin//dat
          data <= {ft_AD,data[31:8]};//先低后高
        end else begin
          command <= ft_AD;
          command_req_ori <= 1;
        end
      end

      debug_data_out_buff <= {8'b0,debug_data_out_buff[31:8]};//低位先送
      if(command_ack)begin
        command_req_ori <= 0;
        if(command_req_ori)begin
          debug_data_out_buff <= debug_data_out;
        end
      end

    end

  end

  reg command_req;
  always @(posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      command_req <= 0;
    end else begin
      command_req <= command_req_ori;
    end
  end

  reg transfer_dly_flg;
  reg [7:0] transfer_dly_cnt;
  reg hiSpeed_buff;
  always @(posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      transfer_dly_flg <= 0;
      hiSpeed_buff <= 0;
      transfer_dly_cnt <= 0;
    end else begin
      hiSpeed_buff <= hiSpeed;
      if(hiSpeed_buff)begin
        //1:hi speed
        transfer_dly_cnt <= transfer_dly_cnt + 1'b1;
        if(transfer_dly_cnt[7])begin
          transfer_dly_flg <= 1;
        end
      end else begin
        //0:command
        transfer_dly_flg <= 0;
        transfer_dly_cnt <= 0;
      end
    end
  end


/*
wire ft_clk;
//IBUFG  IBUFG_ft (.I(ft_AC5_CLKOUT), .O(ft_AC5_CLKOUT_buf));
`ifdef isXC6SLX16
assign ft_clk = ft_AC5_PCLKOUT;
//BUFGMUX BUFGMUX_inst2 (
//  .O(ft_clk),   // 1-bit output: Clock output
//  .I0(ft_AC5_PCLKOUT), // 1-bit input: Clock input (S=0)
//  .I1(ft_AC5_NCLKOUT), // 1-bit input: Clock input (S=1)
//  .S(ft_out_to_pc)    // 1-bit input: Clock select
//);
`else
assign ft_clk = ft_out_to_pc ? ft_AC5_NCLKOUT : ft_AC5_PCLKOUT;
`endif 
*/

// altsource_probe	prob1 (
//       .probe (ft_status),
//       .source ()
//       );
// defparam
//   prob1.enable_metastability = "NO",
//   prob1.instance_id = "P001",
//   prob1.probe_width = 32,
//   prob1.sld_auto_instance_index = "YES",
//   prob1.sld_instance_index = 1,
//   prob1.source_initial_value = " 0",
//   prob1.source_width = 32;

reg RD;
assign ft_AC2_NRD = ~RD;
wire RXF = ~ft_AC0_NRXF;
reg rd_req_buff;
reg rd_ack;
reg [7:0] ft_AD_buff;
always @(negedge ft_AC5_SCLKOUT or negedge reset_n) begin//from pc
  if (!reset_n) begin
    RD <= 0;
    rd_req_buff <= 0;
    rd_ack <= 0;
    ft_AD_buff <= 0;
  end else begin
    RD <= 0;
    rd_req_buff <= rd_req;
    if(rd_req_buff && !rd_ack)begin
      if(RXF)begin
        RD <= 1;
        rd_ack <= 1;
        ft_AD_buff <= ft_AD;
      end
    end
    if(!rd_req_buff && rd_ack)begin
      rd_ack <= 0;
    end
  end
end

reg WR;
assign ft_AC3_NWR = ~WR;
wire TXE = ~ft_AC1_NTXE;
reg wr_req_buff;
reg wr_ack;
always @(posedge ft_AC5_RCLKOUT or negedge reset_n) begin//to pc
  if (!reset_n) begin
    WR <= 0;
    wr_req_buff <= 0;
    wr_ack <= 0;
  end else begin
    WR <= 0;
    wr_req_buff <= wr_req;
    if(wr_req_buff && !wr_ack)begin
      if(TXE)begin
        WR <= 1;
        wr_ack <= 1;
      end
    end
    if(!wr_req_buff && wr_ack)begin
      wr_ack <= 0;
    end
  end
end

reg ft_debug_write;
reg ft_debug_start_send;

wire [7:0] ft_AD_out = ft_read_data_buff[7:0];

reg [31:0] ft_read_data_buff;
reg  [3:0] ft_status;
reg        ft_write; 
reg [31:0] ft_write_data;
wire [31:0] ft_read_data;
reg sync_req_buff;
reg sync_ack;
reg  [FIFO_SIZE:0] ft_addr;
wire [FIFO_SIZE:0] ft_addr_next = ft_addr + 1'b1;
reg  [FIFO_SIZE:0] ft_addr_temp;
reg  [FIFO_SIZE:0] fpga_addr_buff;
reg transfer_dly_flg_buff;
reg ft_out_to_pc_buff;
reg rd_req;
reg rd_ack_buff;
reg wr_req;
reg wr_ack_buff;
always @(posedge clk_25M or negedge reset_n) begin
  if (!reset_n) begin
    ft_status <= 0;
    ft_write <= 0;
    ft_write_data <= 0;
    ft_addr <= 0;
    ft_addr_temp <= 0;
    fpga_addr_buff <= 0;
    sync_req_buff <= 0;
    sync_ack <= 0;
    transfer_dly_flg_buff <= 0;
    ft_out_to_pc_buff <= 0;
    rd_req <= 0;
    rd_ack_buff <= 0;
    wr_req <= 0;
    wr_ack_buff <= 0;
  end else begin
    ft_write <= 0;
    sync_req_buff <= sync_req;
    transfer_dly_flg_buff <= transfer_dly_flg;
    ft_out_to_pc_buff <= ft_out_to_pc;
    rd_ack_buff <= rd_ack;
    wr_ack_buff <= wr_ack;

    if(sync_req_buff && !sync_ack)begin
        sync_ack <= 1;
        ft_addr_temp <= ft_addr;
    end
    if(!sync_req_buff && sync_ack)begin
        sync_ack <= 0;
        fpga_addr_buff <= fpga_addr_temp;
    end

    if(transfer_dly_flg_buff)begin
      if(ft_out_to_pc_buff)begin
        case(ft_status)
        0: begin
          if(ft_addr != fpga_addr_buff)begin//ft_addr读取  fpga_addr_buff写入
            if(!wr_ack_buff)begin
              ft_read_data_buff <= ft_read_data;
              ft_status <= 1;
            end
          end
        end
        1: begin
          wr_req <= 1;
          if(wr_ack_buff)begin
            wr_req <= 0;
            ft_status <= 2;
          end
        end
        2: begin
          if(!wr_ack_buff)begin
            ft_read_data_buff <= {8'b0, ft_read_data_buff[31:8]};
            ft_status <= 3;
          end
        end
        3: begin
          wr_req <= 1;
          if(wr_ack_buff)begin
            wr_req <= 0;
            ft_status <= 4;
          end
        end
        4: begin
          if(!wr_ack_buff)begin
            ft_read_data_buff <= {8'b0, ft_read_data_buff[31:8]};
            ft_status <= 5;
          end
        end
        5: begin
          wr_req <= 1;
          if(wr_ack_buff)begin
            wr_req <= 0;
            ft_status <= 6;
          end
        end
        6: begin
          if(!wr_ack_buff)begin
            ft_read_data_buff <= {8'b0, ft_read_data_buff[31:8]};
            ft_status <= 7;
            ft_addr <= ft_addr + 1'b1;
          end
        end
        7: begin
          wr_req <= 1;
          if(wr_ack_buff)begin
            wr_req <= 0;
            ft_status <= 0;
          end
        end
        endcase

      end else begin
        case(ft_status)
        // pc->fpga 
        0: begin //接收
          rd_req <= 1;
          ft_status <= 1;
        end
        // 14: begin
        //   if(rd_ack_buff)begin
        //     rd_req <= 0;
        //     ft_status <= 15;
        //   end
        // end

        // 15: begin
        //   rd_req <= 1;
        //   ft_status <= 1;
        // end
        1: begin //接收
          if(rd_ack_buff)begin
            rd_req <= 0;
            ft_status <= 2;
          end
        end
        2: begin
          if(!rd_ack_buff)begin
            ft_write_data[7:0] <= ft_AD_buff;//ft_write_data <= {ft_AD_buff, ft_write_data[31:8]};
            ft_status <= 3;
          end
        end
        3: begin //接收
          rd_req <= 1;
          ft_status <= 4;
        end
        4: begin //接收
          if(rd_ack_buff)begin
            rd_req <= 0;
            ft_status <= 5;
          end
        end
        5: begin
          if(!rd_ack_buff)begin
            ft_write_data[15:8] <= ft_AD_buff;//ft_write_data <= {ft_AD_buff, ft_write_data[31:8]};
            ft_status <= 6;
          end
        end
        6: begin //接收
          rd_req <= 1;
          ft_status <= 7;
        end
        7: begin //接收
          if(rd_ack_buff)begin
            rd_req <= 0;
            ft_status <= 8;
          end
        end
        8: begin
          if(!rd_ack_buff)begin
            ft_write_data[23:16] <= ft_AD_buff;//ft_write_data <= {ft_AD_buff, ft_write_data[31:8]};
            ft_status <= 9;
          end
        end
        9: begin //接收
          rd_req <= 1;
          ft_status <= 10;
        end
        10: begin //接收
          if(rd_ack_buff)begin
            rd_req <= 0;
            ft_status <= 11;
          end
        end
        11: begin
          if(!rd_ack_buff)begin
            ft_write_data[31:24] <= ft_AD_buff;//ft_write_data <= {ft_AD_buff, ft_write_data[31:8]};
            ft_status <= 12;
          end
        end
        12: begin
          if(ft_addr_next != fpga_addr_buff)begin//ft_addr写入  fpga_addr_buff读取
            ft_write <= 1;
            ft_status <= 13;
          end
        end
        13: begin
          ft_addr <= ft_addr + 1'b1;
          ft_status <= 0;
        end

        endcase

      end



    end


    if(!hiSpeed || !transfer_dly_flg_buff)begin
      ft_status <= 0;
      ft_addr <= 0;
      rd_req <= 0;
      wr_req <= 0;
    end

  end
end


wire [7:0] ft_debug_data;
`ifdef isISE
  ram32x512 memcpyBuff (
    .clka (clk_25M),
    .wea (ft_write 1111),
    .addra (ft_addr),
    .dina (ft_write_data),
    .douta (ft_read_data),
    
    .clkb (clk),
    .web (fpga_write 1111),
    .addrb (fpga_addr),
    .dinb (fpga_write_data),
    .doutb (fpga_read_data)
  );

`endif
`ifdef isALTERA
altsyncram fifoBuff (
  .clock0 (clk),
  .address_a (ft_addr),
  .data_a (ft_write_data),
  .wren_a (ft_write),
  .q_a (ft_read_data),
  
  .clock1 (clk),
  .address_b (fpga_addr),
  .data_b (fpga_write_data),
  .wren_b (fpga_write),
  .q_b (fpga_read_data),
  
  .aclr0 (1'b0),
  .aclr1 (1'b0),
  .addressstall_a (1'b0),
  .addressstall_b (1'b0),
  .clocken0 (1'b1),
  .clocken1 (1'b1),
  .clocken2 (1'b1),
  .clocken3 (1'b1),
  .eccstatus (),
  .rden_a (1'b1),
  .rden_b (1'b1));
defparam
  fifoBuff.address_reg_b = "CLOCK1",
  fifoBuff.clock_enable_input_a = "BYPASS",
  fifoBuff.clock_enable_input_b = "BYPASS",
  fifoBuff.clock_enable_output_a = "BYPASS",
  fifoBuff.clock_enable_output_b = "BYPASS",
  fifoBuff.indata_reg_b = "CLOCK1",
  fifoBuff.intended_device_family = "Cyclone IV E",
  fifoBuff.lpm_type = "altsyncram",
  fifoBuff.numwords_a = 256,
  fifoBuff.numwords_b = 256,
  fifoBuff.operation_mode = "BIDIR_DUAL_PORT",
  fifoBuff.outdata_aclr_a = "NONE",
  fifoBuff.outdata_aclr_b = "NONE",
  fifoBuff.outdata_reg_a = "UNREGISTERED",
  fifoBuff.outdata_reg_b = "UNREGISTERED",
  fifoBuff.power_up_uninitialized = "FALSE",
  fifoBuff.ram_block_type = "M9K",
  fifoBuff.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
  fifoBuff.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
  fifoBuff.widthad_a = 8,
  fifoBuff.widthad_b = 8,
  fifoBuff.width_a = 32,
  fifoBuff.width_b = 32,
  fifoBuff.width_byteena_a = 1,
  fifoBuff.width_byteena_b = 1,
  fifoBuff.wrcontrol_wraddress_reg_b = "CLOCK1";
`endif


  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  reg [23:0] accessTime;
  reg        accessTimeCnt;
  reg        accessTimeCntLast;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      accessTime <= 0;
      accessTimeCnt <= 0;
      accessTimeCntLast <= 0;
    end else begin
      accessTimeCntLast <= accessTimeCnt;
      if(avm_m0_request || avm_m1_read)begin
        accessTimeCnt <= 1;
      end else begin
        accessTimeCnt <= 0;
      end
      if(accessTimeCnt)begin
        if(!accessTimeCntLast)begin
          accessTime <= 0;
        end else begin
          accessTime <= accessTime + 1'b1;
        end
      end
    end
  end
  

  reg debug_read_ins_reg;
  wire avm_m1_waitrequest_mid;

`ifdef READ_INS
  assign debug_read_ins = debug_read_ins_reg;
  assign avm_m1_waitrequest_mid = avm_m1_waitrequest;
`else
  assign debug_read_ins = 0;
  assign avm_m1_waitrequest_mid = 0;
`endif
  

  assign vga_debugger_read_pixel_clk = clk;

  assign debug_ins_hold_value = 0;
  reg mem_req;
  reg [2:0] mem_cmd;  // 0 MEM_READ       1 MEM_WRITE       2 INS_READ       3 REG_READ
                      // 4 MEM_READ_TRANS 5 MEM_WRITE_TRANS 6 INS_READ_TRANS 7 VGA_TRANS
  reg mem_req_buff;
  reg mem_ack;
  reg [3:0] mem_status;
  reg [31:0] avm_readdata_latch;
  reg sync_req;
  reg sync_ack_buff;
  reg  [FIFO_SIZE:0] ft_addr_buff;
  wire [FIFO_SIZE:0] fpga_addr_next = fpga_addr + 1'b1;
  reg  [FIFO_SIZE:0] fpga_addr_temp;
  reg vga_debugger_read_line_ack_buff;

  wire [31:0] debug_address_end = debug_address + debug_length;

  assign vga_debugger_read_line_part[0] = 0;

  assign {vga_debugger_read_line_addr, vga_debugger_read_line_part[1]} = vga_debugger_read_line_addr_combine;
  reg [16:0] vga_debugger_read_line_addr_combine;
  
  assign vga_debugger_read_pixel_addr = {vga_debugger_read_line_part[1], vga_debugger_read_pixel_cnt};
  reg [8:0] vga_debugger_read_pixel_cnt;
  reg vga_control_by_debugger_accepted_buff;
  reg reset_fifo_buff_fpga;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      mem_ack <= 0;
      mem_req_buff <= 0;
      debug_rw <= 0;
      debug_read_ins_reg <= 0;
      debug_address_data <= 0;
      debug_address_ins <= 0;
      debug_rw_cmd <= 0;
      debug_writedata_data <= 0;
      sync_ack_buff <= 0;

      sync_req <= 0;
      sync_ack_buff <= 0;
      ft_addr_buff <= 0;
      fpga_addr_temp <= 0;
      fpga_addr <= 0;

      vga_debugger_read_line_req <= 0;
      vga_debugger_read_line_addr_combine <= 0;
      vga_debugger_read_line_ack_buff <= 0;
      vga_control_by_debugger <= 0;
      fpga_write <= 0;
      fpga_write_data <= 0;

      vga_debugger_read_pixel_cnt <= 0;
      vga_control_by_debugger_accepted_buff <= 0;
      reset_fifo_buff_fpga <= 0;
    end else begin
      mem_req_buff <= mem_req;
      sync_ack_buff <= sync_ack;
      debug_rw <= 0;
      debug_read_ins_reg <= 0;
      fpga_write <= 0;
      vga_debugger_read_line_ack_buff <= vga_debugger_read_line_ack;
      vga_control_by_debugger_accepted_buff <= vga_control_by_debugger_accepted;
      reset_fifo_buff_fpga <= reset_fifo;

      if(!sync_ack_buff && !sync_req)begin
          sync_req <= 1;
          fpga_addr_temp <= fpga_addr;
      end
      if(sync_ack_buff && sync_req)begin
          sync_req <= 0;
          ft_addr_buff <= ft_addr_temp;
      end
      
      case(mem_status)
      0: begin
        fpga_addr <= 0;
        vga_debugger_read_line_req <= 0;
        debug_address_data <= {debug_address[31:2],2'b0};
        debug_address_ins <= {debug_address[31:2],2'b0};
        vga_debugger_read_line_addr_combine <= debug_address[26:10];//sdram_rw_addr <= {read_line_addr[14:0],2'b(read_line_part),9'b0};//14bit is 2k * 16k 32M,  15bit is 64M
        vga_control_by_debugger <= 0;
        if(mem_req_buff && !mem_ack)begin
          mem_status <= 1;
          if(mem_cmd==VGA_TRANS)begin
            vga_control_by_debugger <= 1;
          end
        end
      end

      1: begin
        case(mem_cmd)
        MEM_READ:begin
          debug_rw_cmd <= 0;// sendCmd(SET_DEBUG_RW_CMD, 0);//ldw
          debug_rw <= 1;
          mem_status <= 2;
        end
        MEM_WRITE:begin
          mem_status <= 8;
        end
        INS_READ:begin
          debug_read_ins_reg <= 1;
          mem_status <= 2;
        end
        REG_READ:begin
          mem_status <= 2;
        end
        MEM_READ_TRANS:begin
          debug_rw_cmd <= 0;// sendCmd(SET_DEBUG_RW_CMD, 0);//ldw
          debug_rw <= 1;
          mem_status <= 2;
        end
        MEM_WRITE_TRANS:begin
          if(fpga_addr != ft_addr_buff)begin
            mem_status <= 8;
          end
        end
        INS_READ_TRANS:begin
          debug_read_ins_reg <= 1;
          mem_status <= 2;
        end
        VGA_TRANS:begin
          if(vga_control_by_debugger_accepted_buff)begin
            mem_status <= 9;
          end
        end
        endcase
      end

      8: begin
        if(mem_cmd[2]==0)begin//MEM_WRITE
          debug_rw_cmd <= 1;//     case 0: debug_rw_cmd = 1; break;//3'b001;//stw
          debug_rw <= 1;
          debug_writedata_data <= debug_writedata;
          mem_status <= 2;
        end else begin
          debug_rw_cmd <= 1;//     case 0: debug_rw_cmd = 1; break;//3'b001;//stw
          debug_rw <= 1;
          debug_writedata_data <= fpga_read_data;
          fpga_addr <= fpga_addr + 1'b1;
          mem_status <= 2;
        end
      end

      9: begin
        if(vga_debugger_read_line_addr_combine==debug_address_end[26:10])begin
          mem_status <= 0;
          mem_ack <= 1;
        end else begin
          mem_status <= 3;
          vga_debugger_read_line_req <= 1;
          vga_debugger_read_pixel_cnt <= 0;
        end        
      end

      2: begin
        mem_status <= 3;
      end

      3: begin
        case(mem_cmd)
        MEM_READ:begin
          if(!avm_m0_waitrequest)begin
            avm_readdata_latch <= avm_m0_readdata;
            mem_status <= 0;
            mem_ack <= 1;
          end
        end
        MEM_WRITE:begin
          if(!avm_m0_waitrequest)begin
            mem_status <= 0;
            mem_ack <= 1;
          end
        end
        INS_READ:begin
          if(!avm_m1_waitrequest_mid)begin
            avm_readdata_latch <= avm_m1_readdata;
            mem_status <= 0;
            mem_ack <= 1;
          end
        end
        REG_READ:begin
          avm_readdata_latch <= debug_regData;
          mem_status <= 0;
          mem_ack <= 1;
        end
        MEM_READ_TRANS:begin
          if(!avm_m0_waitrequest)begin
            avm_readdata_latch <= avm_m0_readdata;
            mem_status <= 4;
          end
        end
        MEM_WRITE_TRANS:begin
          if(!avm_m0_waitrequest)begin
            mem_status <= 4;
          end
        end
        INS_READ_TRANS:begin
          if(!avm_m1_waitrequest_mid)begin
            avm_readdata_latch <= avm_m1_readdata;
            mem_status <= 4;
          end
        end
        VGA_TRANS:begin
          if(vga_debugger_read_line_ack_buff)begin
            vga_debugger_read_line_req <= 0;
            mem_status <= 4;
          end
        end
        endcase
      end

      4: begin
        case(mem_cmd)
        MEM_READ:begin
        end
        MEM_WRITE:begin
        end
        INS_READ:begin
        end
        REG_READ:begin
        end
        MEM_READ_TRANS:begin
          if(ft_addr_buff != fpga_addr_next)begin
            fpga_write_data <= avm_readdata_latch;
            fpga_write <= 1;
            debug_address_data <= debug_address_data + 4;
            mem_status <= 5;
          end
        end
        MEM_WRITE_TRANS:begin
            debug_address_data <= debug_address_data + 4;
            mem_status <= 5;
        end
        INS_READ_TRANS:begin
          if(ft_addr_buff != fpga_addr_next)begin
            fpga_write_data <= avm_readdata_latch;
            fpga_write <= 1;
            debug_address_ins <= debug_address_ins + 4;
            mem_status <= 5;
          end
        end
        VGA_TRANS:begin
          if(ft_addr_buff != fpga_addr_next)begin
            avm_readdata_latch[15:0] <= vga_debugger_read_pixel_data;
            vga_debugger_read_pixel_cnt <= vga_debugger_read_pixel_cnt + 1'b1;
            mem_status <= 5;
          end
        end
        endcase
      end

      5: begin
        case(mem_cmd)
        MEM_READ:begin
        end
        MEM_WRITE:begin
        end
        INS_READ:begin
        end
        REG_READ:begin
        end
        MEM_READ_TRANS:begin
          fpga_addr <= fpga_addr + 1'b1;
          if(debug_address_data != {debug_address_end[31:2],2'b0})begin
            mem_status <= 1;
          end else begin
            mem_status <= 0;
            mem_ack <= 1;
          end
        end
        MEM_WRITE_TRANS:begin
          if(debug_address_data != {debug_address_end[31:2],2'b0})begin
            mem_status <= 1;
          end else begin
            mem_status <= 0;
            mem_ack <= 1;
          end
        end
        INS_READ_TRANS:begin
          fpga_addr <= fpga_addr + 1'b1;
          if(debug_address_ins != {debug_address_end[31:2],2'b0})begin
            mem_status <= 1;
          end else begin
            mem_status <= 0;
            mem_ack <= 1;
          end
        end
        VGA_TRANS:begin
          mem_status <= 6;
        end
        endcase
      end

      6: begin
        fpga_write_data <= {vga_debugger_read_pixel_data, avm_readdata_latch[15:0]};
        fpga_write <= 1;
        vga_debugger_read_pixel_cnt <= vga_debugger_read_pixel_cnt + 1'b1;
        mem_status <= 7;
      end

      7: begin
        fpga_addr <= fpga_addr + 1'b1;
        if(vga_debugger_read_pixel_cnt == 0)begin
          vga_debugger_read_line_addr_combine <= vga_debugger_read_line_addr_combine + 1'b1;
          mem_status <= 9;
        end else begin
          mem_status <= 4;
        end
      end

      endcase
      
      if(!mem_req_buff && mem_ack)begin
        mem_ack <= 0;
      end
      
      if(reset_fifo_buff_fpga)begin
        fpga_addr <= 0;
        mem_status <= 0;
        mem_ack <= 0;
        vga_debugger_read_line_req <= 0;
      end
    end
  end

always @(*)begin
  case(command[5:0])
    

    8'h20: begin debug_data_out<=data; end //GET_CONST_ECHO
    8'h21: begin debug_data_out<=pc_record_data[35:32]; end //GET_PC_RECORD_DATA_EXT
    8'h22: begin debug_data_out<=accessTime; end //GET_ACCESS_TIME
    8'h23: begin debug_data_out<=avm_m0_address; end //GET_AVM_M0_ADDRESS
    8'h24: begin debug_data_out<=`VERSION; end //GET_CONST_ECHO
    8'h25: begin debug_data_out<=pc_record_data[31:0]; end //GET_PC_RECORD_DATA
    8'h26: begin debug_data_out<=pc_record_index; end //GET_PC_RECORD_INDEX
    8'h27: begin debug_data_out<={avm_m1_waitrequest,halt_cpu,halt_debug,avm_m0_waitrequest,irq_enable,irq_req}; end //GET_MISC
    8'h28: begin debug_data_out<=irq_id; end //GET_IRQ_ID
    8'h29: begin debug_data_out<=cpu_address; end //GET_CPU_ADDRESS
    8'h2A: begin debug_data_out<=pc; end // GET_PC
    8'h2B: begin debug_data_out<=memSize; end // GET_MEM_SIZE
    8'h2C: begin debug_data_out<=vga_base_addr; end // GET_VGA_BASE_ADDR
    8'h2D: begin debug_data_out<=mem_cmd; end // TODO del
    8'h2E: begin debug_data_out<=debug_stash_data; end //  GET_DEBUG_STASH_DATA
    8'h2F: begin debug_data_out<=debug_stash_index; end // GET_DEBUG_STASH_INDEX


    8'h30,8'h31,8'h32,8'h33,
    8'h34,8'h35,8'h36,8'h37 : begin//MEM_READ
      debug_data_out <= avm_readdata_latch; 
    end


    default: begin
      debug_data_out<=0;
    end
  endcase
end
  
  reg [31:0] debug_address;
  reg [31:0] debug_writedata;
  reg [31:0] debug_length;
  reg [0:0] debug_mem_step;
  reg [9:0] vga_count;
  reg spirom_debug_read_ack_buff;
  reg spirom_debug_write_ack_buff;
  reg mem_ack_buff;
  reg reset_fifo;
  always @(posedge clk_50M or negedge reset_n) begin
    if (!reset_n) begin
      reset_fifo <= 0;
      
      
      debug_mem_step <= 0;
      
      debug_flg <= 0;

      halt_debug<=1;
      debug_step<=0;
      debug_reset_n<=1;

      debug_address<=0;
      debug_writedata<=0;
      


      command_ack <= 0;
      debug_data_send<=0;
      //debug_data_out<=0;
      
      spirom_debug_read_req<=0;
      spirom_debug_write_req<=0;
      spirom_debug_write_data<=0;
      spirom_debug_cs <= 0;
      spirom_debug_read_ack_buff <= 0;
      spirom_debug_write_ack_buff <= 0;
      
      

      mem_req <= 0;
      mem_ack_buff <= 0;
      mem_cmd <= 0;

      debug_hid <= 0;
      debug_hid_req <= 0;

      //debug_rw_cmd <= 0;//ldw
      
      cpu_clk_sel <= 0;

      debug_commandFifo <= 0;
      debug_commandFifoAddr <= 0;

      //vga_control_by_debugger <= 0;
    end else begin
      spirom_debug_read_ack_buff <=  spirom_debug_read_ack;
      spirom_debug_write_ack_buff <= spirom_debug_write_ack;

      mem_ack_buff <= mem_ack;
      
      debug_data_send <= 0;

      if(command_req && !command_ack)begin
        case(command[5:0])
        
        
        8'h02 : begin debug_data_send<=1; reset_fifo<=0; command_ack<=1; end //HALT_DEBUG
        8'h03 : begin debug_data_send<=1; reset_fifo<=1; command_ack<=1; end //HALT_DEBUG
        //8'h04 : begin debug_data_send<=1; vga_control_by_debugger<=0; command_ack<=1; end //HALT_DEBUG
        //8'h05 : begin debug_data_send<=1; vga_control_by_debugger<=1; command_ack<=1; end //HALT_DEBUG
        

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        8'h10 : begin debug_data_send<=1; halt_debug<=data[0]; command_ack<=1; end //HALT_DEBUG
        8'h11 : begin debug_data_send<=1; cpu_clk_sel <= data[0]; command_ack<=1; end //SET_CPU_CLK
        8'h12 : begin debug_data_send<=1; debug_reset_n<=data[0]; command_ack<=1; end //DEBUG_RESET_N
        8'h14 : begin debug_data_send<=1; debug_step<=~debug_step; command_ack<=1; end //DEBUG_STEP
        //8'h15 : begin debug_data_send<=1; debug_rw_cmd <= data[2:0]; command_ack<=1; end//SET_DEBUG_RW_CMD
        8'h16 : begin debug_data_send<=1; debug_address <= data; command_ack<=1; end//SET_DEBUG_ADDRESS
        8'h17 : begin debug_data_send<=1; debug_writedata <= data; command_ack<=1; end//SET_DEBUG_WRITEDATA
        8'h18 : begin debug_data_send<=1; debug_vga_base_addr<= data; command_ack<=1; end // SET_DEBUG_VGA_BASE_ADDR
        8'h19 : begin debug_data_send<=1; debug_flg <= data[0]; command_ack<=1; end //SET_DEBUG_FLG
        8'h1A : begin debug_data_send<=1; debug_hid <= data; command_ack<=1; end //SET_DEBUG_HID
        8'h1B : begin debug_data_send<=1; debug_hid_req <= data[0]; command_ack<=1; end //SET_DEBUG_HID_REQ
        8'h1C : begin debug_data_send<=1; debug_length <= data; command_ack<=1; end //SET_DEBUG_LENGTH

        8'h20,8'h21,8'h22,8'h23,8'h24,8'h25,8'h26,8'h27,
        8'h28,8'h29,8'h2A,8'h2B,8'h2C,8'h2D,8'h2E,8'h2F : begin
          debug_data_send<=1; command_ack<=1;
        end //GET_CONST_ECHO

        8'h30,8'h31,8'h32,8'h33 : begin
          if         (debug_mem_step==0)begin
            debug_mem_step <= 1;
            mem_req <= 1;
            mem_cmd <= command[2:0];
          end else if(debug_mem_step==1)begin
            if(mem_ack_buff)begin
              mem_req <= 0;
              debug_mem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end
        8'h34,8'h35,8'h36,8'h37 : begin
          if         (debug_mem_step==0)begin
            debug_mem_step <= 1;
            mem_req <= 1;
            mem_cmd <= command[2:0];
          end else if(debug_mem_step==1)begin
            debug_mem_step <= 0;
            command_ack <= 1;
          end
        end



        default: begin
          command_ack<=1;
        end

        
        endcase

      end

      if(!command_req && command_ack)begin
        command_ack<=0;
      end
      
      if(!debug_tx_to_pc_valid && debug_tx_to_pc_read)begin
        debug_tx_to_pc_read <= 0;
      end
      
      if(debug_rx_from_pc_read && debug_rx_from_pc_valid)begin
        debug_rx_from_pc_valid <= 0;
      end

      if(mem_ack_buff)begin
        mem_req <= 0;
      end

      if(reset_fifo)begin
        debug_mem_step <= 0;
        mem_req <= 0;
      end
    end
  end



endmodule
